#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<unistd.h>
#include<arpa/inet.h>
// 多线程
#include<pthread.h>
#include "threadpool.h"

// 信息结构体
struct SockInfo
{
    struct sockaddr_in cliaddr;
    int fd;
};

typedef struct PoolInfo
{
    ThreadPool* p;
    int fd;
}PoolInfo;
// struct SockInfo infos[512];

void working(void *arg);
void acceptConn(void* arg);

int main(){
    // 1. 创建监听的套接字
    int fd = socket(AF_INET, SOCK_STREAM, 0);
    if(fd == -1){
        perror("socket");
        return -1;
    }
    // 2. 绑定
    struct sockaddr_in saddr;
    saddr.sin_family = AF_INET;
    saddr.sin_port = htons(9999);
    saddr.sin_addr.s_addr = INADDR_ANY; // 0 = 0.0.0.0
    int ret = bind(fd, (struct sockaddr*)&saddr, sizeof(saddr));
    if( ret == -1){
        perror("bind");
        return -1;
    }
    // 3. 监听
    ret = listen(fd, 128);
    if(ret == -1){
        perror("listen");
        return -1;
    }

    // 初始化结构体数组
    // int max = sizeof(infos)/sizeof(infos[0]);
    // for(int i = 0; i < max; i++){
    //     bzero(&infos[i], sizeof(infos[i]));
    //     infos[i].fd = -1;// 空闲
    // }

    // 创建线程池
    ThreadPool* pool = threadPoolCreate(3, 8, 100);
    PoolInfo* info =  (PoolInfo*)malloc(sizeof(PoolInfo));
    info->fd = fd;
    info->p = pool;
    threadPoolAdd(pool, acceptConn, info);

    pthread_exit(NULL);
    return 0;
}
void acceptConn(void* arg){
    PoolInfo* poolInfo = (PoolInfo*)arg;
    // 4. 阻塞等待客户端的连接（主线程）
    // struct sockaddr_in cliaddr;
    int addelen = sizeof(struct sockaddr_in);
    while(1){
        struct SockInfo* pinfo;
        // for(int i = 0; i < max; i++){
        //     if(infos[i].fd == -1){
        //         pinfo = &infos[i];
        //         break;
        //     }
        // }
        pinfo = (struct SockInfo*)malloc(sizeof(struct SockInfo));
        // int cfd = accept(fd, (struct sockaddr*)&pinfo->cliaddr, &addelen);
        pinfo->fd = accept(poolInfo->fd, (struct sockaddr*)&pinfo->cliaddr, &addelen);
        // pinfo->fd = cfd;

        if(pinfo->fd == -1){
            perror("accept");
            break;
        }
        // 创建子线程
        // pthread_t tid;
        // pthread_create(&tid, NULL, working, pinfo);
        // pthread_detach(tid);//join是阻塞函数，主线程回收资源

        // 添加通信任务
        threadPoolAdd(poolInfo->p, working, pinfo);
    }
    close(poolInfo->fd);
}
void working(void* arg)
{
    struct SockInfo* pinfo = (struct SockInfo*)arg;
    // 连接成功，打印客户端的IP和端口信息
    char ip[32];
    printf("客户端的IP地址是：%s, 端口是：%d\n", inet_ntop(AF_INET, &pinfo->cliaddr.sin_addr.s_addr, ip, sizeof(ip)), ntohs(pinfo->cliaddr.sin_port));
    // 5. 通信（子线程）
    while(1){
        char recvbuf[1024];
        int len = recv(pinfo->fd, recvbuf, sizeof(recvbuf), 0);
        if(len > 0 ){
            printf("客户端说：%s\n", recvbuf);
            send(pinfo->fd, recvbuf, len, 0);
        }
        else if(len == 0){
            printf("客户端断开连接\n");
            break;
        }
        else{
            perror("recv");
            break;
        }
    }

    // 关闭文件描述符
    close(pinfo->fd);
    // pinfo->fd = -1;

    // return NULL;
}